package com.dd.cloud.user.service.consule.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.ConsultConstants;
import com.dd.cloud.common.constants.TencentConstants;
import com.dd.cloud.common.utils.JsonUtils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.DTO.tencent.*;
import com.dd.cloud.user.DTO.tencent.chatMsg.*;
import com.dd.cloud.user.config.TencentImProperties;
import com.dd.cloud.user.entity.consult.ConsultSubscribe;
import com.dd.cloud.user.entity.consult.TencentImMsg;
import com.dd.cloud.user.entity.file.FileInfo;
import com.dd.cloud.user.mapper.consult.TencentImMsgMapper;
import com.dd.cloud.user.req.consult.ImCreateUserReq;
import com.dd.cloud.user.req.consult.ImUpdateAccountReq;
import com.dd.cloud.user.req.consult.ImUpdateUserInfoReq;
import com.dd.cloud.user.req.consult.ImUpdateUserReq;
import com.dd.cloud.user.service.consule.IConsultSubscribeService;
import com.dd.cloud.user.service.consule.ITencentImMsgService;
import com.dd.cloud.user.service.file.IFileInfoService;
import com.dd.cloud.user.service.log.ILogErrorService;
import com.dd.cloud.user.util.TLSSigAPIv2;
import com.dd.cloud.user.util.WordToPdf;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 * 腾讯im聊天消息表 服务实现类
 * </p>
 *
 * @author czg
 * @since 2023-07-07
 */
@Service
@Slf4j
public class TencentImMsgServiceImpl extends ServiceImpl<TencentImMsgMapper, TencentImMsg> implements ITencentImMsgService {
    @Autowired
    private TencentImProperties tencentImProperties;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ILogErrorService logErrorService;
    @Autowired
    @Lazy
    private IConsultSubscribeService consultSubscribeService;
    @Autowired
    private IFileInfoService fileInfoService;
    @Autowired
    private TransactionDefinition transactionDefinition;


    /**
     * @param request:
     * @param urlReq:
     * @param sinParamReq:
     * @return ImCallbackRes
     * @description im消息单聊回调
     * @author czg
     * @date 2023/7/7 15:15
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ImCallbackRes imSinmsgCallback(HttpServletRequest request, ImCallbackUrlParamReq urlReq, ImCallbackSinParamReq sinParamReq) {
        String medId = null;
        String fromAccount = sinParamReq.getFrom_Account();
        String toAccount = sinParamReq.getTo_Account();
        if (fromAccount == null || fromAccount.indexOf("_") <= 0) {
            log.info("im发送者id缺失,{}", fromAccount);
            return ImCallbackRes.ok();
        }
        if (toAccount == null || toAccount.indexOf("_") <= 0) {
            log.info("im接收者id缺失,{}", fromAccount);
            return ImCallbackRes.ok();
        }
        String[] from = fromAccount.split("_");
        String[] to = toAccount.split("_");
        TencentImMsg tencentImMsg = new TencentImMsg();
        tencentImMsg.setMsgKey(sinParamReq.getMsgKey());
        try {
            tencentImMsg.setFromUser(Integer.valueOf(from[0]));
            tencentImMsg.setFromUserType(Integer.valueOf(from[1]));
            tencentImMsg.setToUser(Integer.valueOf(to[0]));
            tencentImMsg.setToUserType(Integer.valueOf(to[1]));
            //患者聊天id 为患者id_患者类型_就诊卡id 需要另外处理
            if (LoginInfo.UserType.PATIENT == tencentImMsg.getFromUserType()) {
                medId = from[2];
            } else {
                medId = to[2];
            }
        } catch (Exception e) {
            logErrorService.presBackLog("id转换失败", "后台发送im单聊消息返回异常", "res=" + sinParamReq.toString());
            e.printStackTrace();
        }
        tencentImMsg.setMedId(medId);
        /**
         * 2023-08-05此处逻辑,客户端发送微信im消息, 文本音频视频回调时无CloudCustomData(预约id)参数, java后台发送的消息有此参数
         * 如果没有此参数,暂时通过业务关联去查询预约id
         * 后期腾讯imsdk更新后需要使用CloudCustomData参数传递预约id
         */
        Integer consultId = null;
        if (!StringUtils.isBlank(sinParamReq.getCloudCustomData())) {
            try {
                consultId = Integer.valueOf(sinParamReq.getCloudCustomData());
            } catch (Exception e) {
                log.error("CloudCustomData转预约id失败,{}", sinParamReq.getCloudCustomData());
            }
        }
        QueryWrapper<ConsultSubscribe> qw = new QueryWrapper<>();
        if (tencentImMsg.getFromUserType() == LoginInfo.UserType.DOCTOR) {
            ConsultSubscribe one = null;
            if (consultId == null) {
                //医生给患者发消息 查询是否有进行中的预约
                qw.lambda().eq(ConsultSubscribe::getDoctorId, tencentImMsg.getFromUser())
                        .eq(ConsultSubscribe::getPatientId, tencentImMsg.getToUser())
                        //.ge(ConsultSubscribe::getEndDate, LocalDateTime.now())
                        .eq(ConsultSubscribe::getMedId, medId)
                        .eq(ConsultSubscribe::getStatus, ConsultConstants.Status.UNDERWAY)
                        .orderByDesc(ConsultSubscribe::getEndDate)
                        .last("limit 1");
                one = consultSubscribeService.getOne(qw);
            } else {
                one = consultSubscribeService.getById(consultId);
            }
            if (one != null) {
                //已经有进行中的消息, 不是第一条消息
                consultId = one.getId();
            } else {
                qw.clear();
                qw.lambda().eq(ConsultSubscribe::getDoctorId, tencentImMsg.getFromUser())
                        .eq(ConsultSubscribe::getPatientId, tencentImMsg.getToUser())
                        //.eq(ConsultSubscribe::getDay, LocalDate.now())
                        .eq(ConsultSubscribe::getMedId, medId)
                        .in(ConsultSubscribe::getStatus, ConsultConstants.Status.DOCTOR_CAN_QUE_LIST)
//                        .eq(ConsultSubscribe::getStatus, ConsultConstants.Status.SUBMIT)
                        .orderByDesc(ConsultSubscribe::getEndDate)
                        .last("limit 1");
                one = consultSubscribeService.getOne(qw);
                if (one != null) {
                    consultId = one.getId();
                    if (ConsultConstants.Status.SUBMIT == one.getStatus()) {
                        //开始问诊咨询
                        consultSubscribeService.receivePatientSubscribe(one.getId());
                    }
                }
            }
        } else {
            //患者给医生发消息 直接找进行中的最后一条预约
            qw.lambda().eq(ConsultSubscribe::getDoctorId, tencentImMsg.getToUser())
                    .eq(ConsultSubscribe::getPatientId, tencentImMsg.getFromUser())
                    .ge(ConsultSubscribe::getEndDate, LocalDateTime.now())
                    .eq(ConsultSubscribe::getMedId, medId)
                    .eq(ConsultSubscribe::getStatus, ConsultConstants.Status.UNDERWAY)
                    .orderByDesc(ConsultSubscribe::getEndDate)
                    .last("limit 1");
            ConsultSubscribe one = consultSubscribeService.getOne(qw);
            if (one != null) {
                consultId = one.getId();
            }
        }
        tencentImMsg.setConsultId(consultId);
        tencentImMsg.setCreateDate(LocalDateTime.now());
        tencentImMsg.setStatus(TencentConstants.ImMsgStatus.SEND);
        List<ImCallbackParamTypeReq> msgBody = sinParamReq.getMsgBody();
        AtomicReference<String> msg = new AtomicReference<>("");

        msgBody.forEach(item -> {
            switch (item.getMsgType()) {
                //文本消息
                case "TIMTextElem":
                    ChatCallbackTextMsg textMsg = item.getMsgContent().toJavaObject(ChatCallbackTextMsg.class);
                    msg.set(msg.get() + textMsg.getText());
                    tencentImMsg.setType(TencentConstants.ImMsgType.TEXT);
                    tencentImMsg.setContent(msg.get());
                    break;
                //位置消息
                case "TIMLocationElem":
                    ChatCallbackLocationMsg locationMsg = item.getMsgContent().toJavaObject(ChatCallbackLocationMsg.class);

                    break;
                //表情消息
                case "TIMFaceElem":
                    ChatCallbackFaceMsg faceMsg = item.getMsgContent().toJavaObject(ChatCallbackFaceMsg.class);
                    tencentImMsg.setType(TencentConstants.ImMsgType.FACE);
                    tencentImMsg.setContent(faceMsg.getData());
                    break;
                //自定义消息
                case "TIMCustomElem":
                    ChatCallbackCustomMsg customMsg = item.getMsgContent().toJavaObject(ChatCallbackCustomMsg.class);
                    tencentImMsg.setType(TencentConstants.ImMsgType.CUSTOM);
                    tencentImMsg.setContent(customMsg.getData());

                    break;
                //音频消息
                case "TIMSoundElem":
                    ChatCallbackSoundMsg soundMsg = item.getMsgContent().toJavaObject(ChatCallbackSoundMsg.class);
                    tencentImMsg.setType(TencentConstants.ImMsgType.SOUND);
                    File urlHttp = WordToPdf.getNetUrlHttp(soundMsg.getUrl());
                    FileInfo fileInfo = fileInfoService.uploadSingleFile(urlHttp);
                    soundMsg.setUrl(fileInfo.getFileUrl());
                    tencentImMsg.setUrl(fileInfo.getFileUrl());
                    tencentImMsg.setContent(JsonUtils.objectToStr(soundMsg));
                    break;
                //图片消息
                case "TIMImageElem":
                    ChatCallbackImgMsg imgMsg = item.getMsgContent().toJavaObject(ChatCallbackImgMsg.class);
                    tencentImMsg.setType(TencentConstants.ImMsgType.IMG);
                    for (ChatCallbackImgMsg.ImageInfo image :
                            imgMsg.getImageInfoArray()) {
                        String source = image.getURL();
                        File imgFile = WordToPdf.getNetUrlHttp(source);
                        FileInfo fileInfo2 = fileInfoService.uploadSingleFile(imgFile);
                        image.setURL(fileInfo2.getFileUrl());
                    }
                    tencentImMsg.setUrl(imgMsg.getImageInfoArray().get(0).getURL());
                    tencentImMsg.setContent(JsonUtils.objectToStr(imgMsg.getImageInfoArray()));
                    break;
                //文件消息
                case "TIMFileElem":
                    ChatCallbackFileMsg fileMsg = item.getMsgContent().toJavaObject(ChatCallbackFileMsg.class);
                    tencentImMsg.setType(TencentConstants.ImMsgType.FILE);
                    File fileHttp = WordToPdf.getNetUrlHttp(fileMsg.getUrl());
                    FileInfo fileInfo3 = fileInfoService.uploadSingleFile(fileHttp);
                    fileMsg.setUrl(fileInfo3.getFileUrl());
                    tencentImMsg.setUrl(fileInfo3.getFileUrl());
                    tencentImMsg.setContent(JsonUtils.objectToStr(fileMsg));
                    break;
                //视频消息
                case "TIMVideoFileElem":
                    ChatCallbackVideoMsg videoMsg = item.getMsgContent().toJavaObject(ChatCallbackVideoMsg.class);
                    tencentImMsg.setType(TencentConstants.ImMsgType.VIDEO);
                    tencentImMsg.setUrl(videoMsg.getVideoUrl());
                    File videoHttp = WordToPdf.getNetUrlHttp(videoMsg.getVideoUrl());
                    FileInfo fileInfo4 = fileInfoService.uploadSingleFile(videoHttp);
                    tencentImMsg.setUrl(fileInfo4.getFileUrl());
                    tencentImMsg.setContent(JsonUtils.objectToStr(videoMsg));
                    break;
            }
        });


        boolean save = save(tencentImMsg);
        if (!save) {
            return ImCallbackRes.fail("消息保存失败");
        }

        return ImCallbackRes.ok();
    }

    /**
     * @param request:
     * @param urlReq:
     * @param readParamReq:
     * @return ImCallbackRes
     * @description im消息已读回调
     * @author czg
     * @date 2023/7/7 15:15
     */
    @Override
    public ImCallbackRes imReadmsgCallback(HttpServletRequest request, ImCallbackUrlParamReq urlReq, ImCallbackReadParamReq readParamReq) {
        if (urlReq == null || StringUtils.isBlank(urlReq.getCallbackCommand())) {
            return ImCallbackRes.fail("url参数为空");
        }
        if (!tencentImProperties.getSdkappid().equals(urlReq.getSdkAppid())) {
            return ImCallbackRes.fail("sdkappid不一致");
        }
        String fromAccount = readParamReq.getPeer_Account();
        String toAccount = readParamReq.getReport_Account();
        if (fromAccount == null || fromAccount.indexOf("_") <= 0) {
            log.info("im发送者id缺失,{}", fromAccount);
            return ImCallbackRes.ok();
        }
        if (toAccount == null || toAccount.indexOf("_") <= 0) {
            log.info("im接收者id缺失,{}", fromAccount);
            return ImCallbackRes.ok();
        }
        String[] from = fromAccount.split("_");
        String[] to = toAccount.split("_");
        String medId = null;
        Integer doctorId = null;
        Integer patientId = null;
        //患者聊天id 为患者id_患者类型_就诊卡id 需要另外处理
        if (LoginInfo.UserType.PATIENT == Integer.valueOf(from[1])) {
            medId = from[2];
            patientId = Integer.parseInt(from[0]);
            doctorId = Integer.parseInt(to[0]);
            log.info("进入消息已读回调----患者id:{},用户id:{},医生id:{}", medId, patientId, doctorId);
        } else {
            medId = to[2];
            patientId = Integer.parseInt(to[0]);
            doctorId = Integer.parseInt(from[0]);
            log.info("进入消息已读回调----患者id:{},用户id:{},医生id:{}", medId, patientId, doctorId);
        }
        UpdateWrapper<TencentImMsg> uw = new UpdateWrapper<>();
        uw.lambda().eq(TencentImMsg::getFromUser, from[0])
                .eq(TencentImMsg::getMedId, medId)
                .eq(TencentImMsg::getFromUserType, from[1])
                .eq(TencentImMsg::getToUser, to[0])
                .eq(TencentImMsg::getToUserType, to[1])
                .eq(TencentImMsg::getStatus, TencentConstants.ImMsgStatus.SEND)
                .set(TencentImMsg::getStatus, TencentConstants.ImMsgStatus.READ);
        boolean b = update(uw);
        if (!b) {
            //此时是有可能已读回调先于消息回调到达, 配置了回调失败重试机制, 只有一次, 先睡眠1秒,保证消息回调到达
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
            return ImCallbackRes.fail("已读修改失败");

        }
        return ImCallbackRes.ok();
    }

    /**
     * @param request:
     * @param urlReq:
     * @param recallParamReq:
     * @return ImCallbackRes
     * @description im消息撤回回调
     * @author czg
     * @date 2023/7/7 15:15
     */
    @Override
    public ImCallbackRes imRecallmsgCallback(HttpServletRequest request, ImCallbackUrlParamReq urlReq, ImCallbackRecallParamReq recallParamReq) {
        if (urlReq == null || StringUtils.isBlank(urlReq.getCallbackCommand())) {
            return ImCallbackRes.fail("url参数为空");
        }
        if (!tencentImProperties.getSdkappid().equals(urlReq.getSdkAppid())) {
            return ImCallbackRes.fail("sdkappid不一致");
        }
        UpdateWrapper<TencentImMsg> uw = new UpdateWrapper<>();
        uw.lambda().eq(TencentImMsg::getMsgKey, recallParamReq.getMsgKey())
                .set(TencentImMsg::getStatus, TencentConstants.ImMsgStatus.RECALL);
        boolean update = update(uw);
        if (!update) {
            return ImCallbackRes.fail("撤回修改失败");

        }
        return ImCallbackRes.ok();

    }

    /**
     * @param req:
     * @return void
     * @description 发送单聊消息
     * @author czg
     * @date 2023/7/17 14:45
     */
    @Override
    public void imSendmsgSin(ImSendmsgSinParamReq req) {
        ObjectMapper objectMapper = new ObjectMapper();
        ImSendmsgUrlParamReq imSendmsgUrlParamReq = new ImSendmsgUrlParamReq();
        imSendmsgUrlParamReq.setIdentifier("administrator");
        imSendmsgUrlParamReq.setSdkappid(tencentImProperties.getSdkappid());
        TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(tencentImProperties.getSdkappid(), tencentImProperties.getKey());
        String userSig = tlsSigAPIv2.genUserSig("administrator", tencentImProperties.getExpire());
        imSendmsgUrlParamReq.setUsersig(userSig);
        Random random = new Random();
        int signedNumber = random.nextInt();
        long unsignedNumber = signedNumber & 0xffffffffL;
        imSendmsgUrlParamReq.setRandom(unsignedNumber);
        //req.setSyncOtherMachine(1);
        req.setMsgRandom(unsignedNumber);
        req.setMsgSeq(unsignedNumber);
        String sendMsgUrl = String.format(tencentImProperties.getSendMsgUrl(), imSendmsgUrlParamReq.getSdkappid(),
                imSendmsgUrlParamReq.getIdentifier(),
                imSendmsgUrlParamReq.getUsersig(),
                imSendmsgUrlParamReq.getRandom(),
                imSendmsgUrlParamReq.getContenttype());
        log.info("发送单聊消息url:{}", sendMsgUrl);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        try {
            HttpEntity<String> request = new HttpEntity<>(objectMapper.writeValueAsString(req), headers);
            // 发起请求
            log.info("发送单聊消息参数:{}", objectMapper.writeValueAsString(req));
            String res = restTemplate.postForObject(sendMsgUrl, request, String.class);
            log.info("单聊消息发送结果:{}", res);
            ImSendmsgSinRes imSendmsgSinRes = objectMapper.readValue(res, ImSendmsgSinRes.class);
            if (imSendmsgSinRes.getActionStatus().equals("FAIL")) {
                //发送失败
                logErrorService.presBackLog("单聊消息发送失败", "后台发送im单聊消息返回异常", "res=" + imSendmsgSinRes.toString());
            }
        } catch (Exception e) {

        }
    }

    /**
     * @param sinParamReq:
     * @return void
     * @description 后台发送text消息, 测试用
     * @author czg
     * @date 2023/7/31 14:42
     */
    @Override
    public void imSendmsgTest(ImSendmsgSinParamReq sinParamReq) {
        ImSendParamTypeReq typeReq = new ImSendParamTypeReq();
        ChatCallbackTextMsg textMsg = new ChatCallbackTextMsg();
        textMsg.setText("测试用");
        //自定义消息内容
        ImSendmsgCustomReq imSendmsgCustomReq = new ImSendmsgCustomReq();
        typeReq.setMsgType("TIMTextElem");
        typeReq.setMsgContent(textMsg);
        List<ImSendParamTypeReq> msgBody = new ArrayList<>();
        msgBody.add(typeReq);
        sinParamReq.setMsgBody(msgBody);
        imSendmsgSin(sinParamReq);
    }

    /**
     * @param imMsgCustom:
     * @return void
     * @description 发送自定义系统消息
     * @author czg
     * @date 2023/7/18 15:56
     */
    @Override
    public void imSendmsgSymtem(ImSendmsgSinParamReq sinParamReq, TencentConstants.ImMsgPojo imMsgCustom) {
        ImSendParamTypeReq typeReq = new ImSendParamTypeReq();
        //自定义消息内容
        ImSendmsgCustomReq imSendmsgCustomReq = new ImSendmsgCustomReq();
        imSendmsgCustomReq.setType(imMsgCustom.getType());
        imSendmsgCustomReq.setContent(imMsgCustom.getMsg());
        //自定义消息格式
        ChatCallbackCustomMsg customMsg = new ChatCallbackCustomMsg();

        customMsg.setData(JsonUtils.objectToStr(imSendmsgCustomReq));
        customMsg.setDesc("自定义消息");
        //自定义消息类型
        typeReq.setMsgType("TIMCustomElem");

        typeReq.setMsgContent(customMsg);
        List<ImSendParamTypeReq> msgBody = new ArrayList<>();
        msgBody.add(typeReq);
        sinParamReq.setMsgBody(msgBody);
        imSendmsgSin(sinParamReq);
    }

    /**
     * @param sinParamReq: 消息参数
     * @param imMsgCustom: 模板内容
     * @param param:       额外参数 建议为json字符串
     * @return void
     * @description 发送自定义消息 添加额外参数
     * @author czg
     * @date 2023/8/14 15:21
     */
    @Override
    public void imSendmsgSymtem(ImSendmsgSinParamReq sinParamReq, TencentConstants.ImMsgPojo imMsgCustom, String param) {
        ImSendParamTypeReq typeReq = new ImSendParamTypeReq();
        //自定义消息内容
        ImSendmsgCustomReq imSendmsgCustomReq = new ImSendmsgCustomReq();
        imSendmsgCustomReq.setType(imMsgCustom.getType());
        imSendmsgCustomReq.setContent(imMsgCustom.getMsg());
        imSendmsgCustomReq.setCustomData(param);
        //自定义消息格式
        ChatCallbackCustomMsg customMsg = new ChatCallbackCustomMsg();

        customMsg.setData(JsonUtils.objectToStr(imSendmsgCustomReq));
        customMsg.setDesc("自定义消息");
        //自定义消息类型
        typeReq.setMsgType("TIMCustomElem");

        typeReq.setMsgContent(customMsg);
        List<ImSendParamTypeReq> msgBody = new ArrayList<>();
        msgBody.add(typeReq);
        sinParamReq.setMsgBody(msgBody);
        imSendmsgSin(sinParamReq);
    }

    /**
     * @param req:
     * @return void
     * @description 发送系统消息, 测试用
     * @author czg
     * @date 2023/7/18 18:13
     */
    @Override
    public void imSendmsgAsymptomSymtem(ImSendmsgSinParamReq req) {
        TencentConstants.ImMsgPojo imMsgPojo = new TencentConstants.ImMsgPojo();
        imSendmsgSymtem(req, imMsgPojo.imMsgSet(TencentConstants.ImMsgCustom.ASYMPTOM, null));

    }

    /**
     * @param request:
     * @param urlReq:
     * @param map:
     * @return ImCallbackRes
     * @description im消息回调
     * @author czg
     * @date 2023/7/19 9:59
     */
    @Override
    public ImCallbackRes imMsgCallback(HttpServletRequest request, ImCallbackUrlParamReq urlReq, Map map) {
        if (urlReq == null || StringUtils.isBlank(urlReq.getCallbackCommand())) {
            return ImCallbackRes.fail("url参数为空");
        }
        if (!tencentImProperties.getSdkappid().equals(urlReq.getSdkAppid())) {
            return ImCallbackRes.fail("sdkappid不一致");
        }
        if (map == null || map.isEmpty()) {
            return ImCallbackRes.fail("body参数为空");
        }
        String callbackCommand = (String) map.get("CallbackCommand");
        if (StringUtils.isBlank(callbackCommand)) {
            return ImCallbackRes.fail("回调格式错误");
        }
        ImCallbackRes imCallbackRes = new ImCallbackRes();
        JSONObject jsonObject = new JSONObject(map);

        log.info("参数转换json:{}", jsonObject);
        switch (callbackCommand) {
            case "C2C.CallbackAfterSendMsg":
                //单发消息
                ImCallbackSinParamReq sinParamReq = JSON.parseObject(JSON.toJSONString(jsonObject), ImCallbackSinParamReq.class);
                log.info("单聊消息参数:{}", sinParamReq);
                imCallbackRes = imSinmsgCallback(request, urlReq, sinParamReq);
                break;
            case "C2C.CallbackAfterMsgReport":
                //消息已读
                ImCallbackReadParamReq readParamReq = JSON.parseObject(JSON.toJSONString(jsonObject), ImCallbackReadParamReq.class);
                imCallbackRes = imReadmsgCallback(request, urlReq, readParamReq);
                break;
            case "C2C.CallbackAfterMsgWithDraw":
                //消息撤回
                ImCallbackRecallParamReq recallParamReq = JSON.parseObject(JSON.toJSONString(jsonObject), ImCallbackRecallParamReq.class);
                imCallbackRes = imRecallmsgCallback(request, urlReq, recallParamReq);
                break;
        }
        return imCallbackRes;
    }

    /**
     * @param list: 用户列表参数
     * @return void
     * @description im即时通信创建用户
     * @author czg
     * @date 2023/8/4 9:21
     */
    @Async
    @Override
    public void imCreateImUser(List<ImCreateUserReq> list) {
        for (ImCreateUserReq user :
                list) {
            TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(tencentImProperties.getSdkappid(), tencentImProperties.getKey());
            String userSig = tlsSigAPIv2.genUserSig("administrator", tencentImProperties.getExpire());
            ObjectMapper objectMapper = new ObjectMapper();
            Random random = new Random();
            int signedNumber = random.nextInt();
            long unsignedNumber = signedNumber & 0xffffffffL;
            String sendMsgUrl = String.format(tencentImProperties.getCreateUserUrl(), tencentImProperties.getSdkappid(),
                    userSig,
                    unsignedNumber,
                    "json");
            log.info("创建用户url:{}", sendMsgUrl);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            ImImportAccountReq imImportAccountReq = new ImImportAccountReq();
            if (LoginInfo.UserType.PATIENT == user.getUserType()) {
                imImportAccountReq.setUserID(user.getUserId() + "_" + user.getUserType() + "_" + user.getMedId());
            } else {
                imImportAccountReq.setUserID(user.getUserId() + "_" + user.getUserType());
            }
            imImportAccountReq.setNick(user.getUserName());
            imImportAccountReq.setFaceUrl(user.getFaceUrl());
            try {
                HttpEntity<String> request = new HttpEntity<>(objectMapper.writeValueAsString(imImportAccountReq), headers);
                // 发起请求
                log.info("创建im用户参数:{}", objectMapper.writeValueAsString(imImportAccountReq));
                String res = restTemplate.postForObject(sendMsgUrl, request, String.class);
                log.info("创建im用户返回:{}", res);
                ImSendmsgSinRes imSendmsgSinRes = objectMapper.readValue(res, ImSendmsgSinRes.class);
                if (imSendmsgSinRes.getActionStatus().equals("FAIL")) {
                    //发送失败
                    logErrorService.presBackLog("创建im用户返回失败", "创建im用户返回失败", "res=" + imSendmsgSinRes.toString());
                }
            } catch (Exception e) {
                logErrorService.presBackLog("创建im用户返回异常报错", "创建im用户返回失败", "res=" + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * @param user: 用户
     * @return void
     * @description im即时通信修改用户资料
     * @author czg
     * @date 2023/8/4 9:21
     */
    @Async
    @Override
    public void imUpdateImUser(ImUpdateUserReq user) {
        TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(tencentImProperties.getSdkappid(), tencentImProperties.getKey());
        String userSig = tlsSigAPIv2.genUserSig("administrator", tencentImProperties.getExpire());
        ObjectMapper objectMapper = new ObjectMapper();
        Random random = new Random();
        int signedNumber = random.nextInt();
        long unsignedNumber = signedNumber & 0xffffffffL;
        String sendMsgUrl = String.format(tencentImProperties.getUpdateUserUrl(), tencentImProperties.getSdkappid(),
                userSig,
                unsignedNumber,
                "json");
        log.info("修改用户url:{}", sendMsgUrl);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        ImUpdateAccountReq imUpdateUserReq = new ImUpdateAccountReq();
        if (LoginInfo.UserType.PATIENT == user.getUserType()) {
            imUpdateUserReq.setFrom_Account(user.getUserId() + "_" + user.getUserType() + "_" + user.getMedId());
        } else {
            imUpdateUserReq.setFrom_Account(user.getUserId() + "_" + user.getUserType());
        }
        List<ImUpdateUserInfoReq> profileItems = new ArrayList<>();
        ImUpdateUserInfoReq imUpdateUserNick = new ImUpdateUserInfoReq();
        imUpdateUserNick.setTag("Tag_Profile_IM_Nick");
        imUpdateUserNick.setValue(user.getUserName());
        profileItems.add(imUpdateUserNick);
        ImUpdateUserInfoReq imUpdateUserImage = new ImUpdateUserInfoReq();
        imUpdateUserImage.setTag("Tag_Profile_IM_Image");
        imUpdateUserImage.setValue(user.getFaceUrl());
        profileItems.add(imUpdateUserImage);
        imUpdateUserReq.setProfileItem(profileItems);
        try {
            HttpEntity<String> request = new HttpEntity<>(objectMapper.writeValueAsString(imUpdateUserReq), headers);
            // 发起请求
            log.info("修改im用户参数:{}", objectMapper.writeValueAsString(imUpdateUserReq));
            String res = restTemplate.postForObject(sendMsgUrl, request, String.class);
            log.info("修改im用户返回:{}", res);
            ImSendmsgSinRes imSendmsgSinRes = objectMapper.readValue(res, ImSendmsgSinRes.class);
            if (imSendmsgSinRes.getActionStatus().equals("FAIL")) {
                //发送失败
                logErrorService.presBackLog("修改im用户返回失败", "修改im用户返回失败", "res=" + imSendmsgSinRes.toString());
            }
        } catch (Exception e) {
            logErrorService.presBackLog("修改im用户返回异常报错", "修改im用户返回失败", "res=" + e.getMessage());
            e.printStackTrace();
        }

    }

}
